package avicit.bdp.dcs.threshold.batch;

import avicit.bdp.dcs.job.dto.JobDTO;
import avicit.bdp.dcs.threshold.utils.TestUtils;
import avicit.platform6.core.rest.msg.ResponseMsg;
import com.alibaba.fastjson2.JSON;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;

/** 批量测试 */
public class BatchExecutorTest {
  private RestTemplate restTemplate = new RestTemplate();

  private static final int BATCH_SIZE = 10;

  private static String srcTble = "batch_src_" + System.currentTimeMillis();

  private String[] dstTblNames = new String[BATCH_SIZE];

  /** 所有用例执行前准备工作 */
  @BeforeClass
  public static void init() {
    // TODO:
  }

  /** 单个测试用例运行前准备工作 */
  @Before
  public void setUp() {
    System.out.println("用例初始化...");
    TestUtils.insert2Mysql(srcTble);
  }

  /** 单个测试用例运行后销毁工作 */
  @After
  public void tearDown() {
    System.out.println("用例执行完成，开始清理...");
    TestUtils.deleteFromMysql(srcTble);
    for (String dstTlbName : dstTblNames) {
      TestUtils.deleteFromMysql(dstTlbName);
    }
  }

  /** 所有用例执行完成后准备工作 */
  @AfterClass
  public static void destory() {
    // TODO:
  }

  /** 新建Job，返回创建的JobId */
  private String createJob(String dstTble) {
    String jobId = null;
    boolean flag = true;
    try {
      // step1:保存数据源
      ResponseEntity<ResponseMsg> result =
          restTemplate.postForEntity(
              TestUtils.HOSTPORT + "/api/bdp/dcs/job/JobRest/saveDataSource",
              TestUtils.buildSaveDataSourceParas(
                  2,
                  "批量测试门槛用例",
                  TestUtils.MYSQL_SRC_DATASOURCE_ID,
                  TestUtils.MYSQL_DST_DATASOURCE_ID,
                  1),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      if (!result.getBody().getRetCode().equals("200")) {
        throw new IOException("保存数据源信息失败");
      }

      // 获取创建的JobId
      ResponseMsg responseMsg = result.getBody();
      Map<String, String> jobMap = (Map<String, String>) responseMsg.getResponseBody();
      jobId = jobMap.get("jobId");

      // step2:保存表映射关系
      result =
          restTemplate.postForEntity(
              TestUtils.HOSTPORT + "/api/bdp/dcs/job/JobRest/saveTableMapping",
              TestUtils.buildSaveTblMapping(2, jobId, srcTble, dstTble),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      if (!result.getBody().getRetCode().equals("200")) {
        throw new IOException("保存表映射关心失败");
      }

      // step3:任务配置检查
      result =
          restTemplate.postForEntity(
              TestUtils.HOSTPORT + "/api/bdp/dcs/job/JobRest/checkTaskConfig",
              TestUtils.buildCheckTaskConfig(jobId),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      if (!result.getBody().getRetCode().equals("200")) {
        throw new IOException("任务配置检查失败");
      }

      // step4:预检查
      result =
          restTemplate.postForEntity(
              TestUtils.HOSTPORT + "/api/bdp/dcs/precheck/PrecheckRest" + "/executePrecheck",
              TestUtils.buildPreChecks(jobId),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      if (!result.getBody().getRetCode().equals("200")) {
        throw new IOException("预检查失败");
      }

      // step5:更新Job状态
      result =
          restTemplate.postForEntity(
              TestUtils.HOSTPORT + "/api/bdp/dcs/job/JobRest/updateJobStatus",
              TestUtils.buildUpdateJobStatus(jobId),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      if (!result.getBody().getRetCode().equals("200")) {
        throw new IOException("更新Job状态失败");
      }
    } catch (Exception e) {
      flag = false;
      jobId = null;
    }

    return jobId;
  }

  /***********************************************Begin 测试用例 ***********************************************/
  /**
   * step1:批量创建任务；step2:批量删除任务;(预期结果：success,success)
   *
   * @throws Exception
   */
  @Test(timeout = 5 * 60 * 1000)
  public void testbatchExecutorTest1() throws Exception {
    StringBuilder sb = new StringBuilder();

    try {
      // step1:；批量创建任务
      for (int i = 0; i < BATCH_SIZE; i++) {
        long currTime = System.currentTimeMillis();
        String jobId = createJob("BatchExecutorTest_" + currTime + "_" + i);
        assertEquals(jobId != null, true);
        sb.append(jobId);
        if (i != BATCH_SIZE - 1) {
          sb.append(",");
        }

        dstTblNames[i] = "BatchExecutorTest_" + currTime + "_" + i;
      }
      System.out.println("批量创建任务ids=" + sb.toString());
    } finally {
      // step2:批量删除任务
      ResponseEntity<ResponseMsg> result =
          restTemplate.exchange(
              TestUtils.HOSTPORT + "/api/bdp/dcs/job/JobRest" + "/deleteJobByIds",
              HttpMethod.DELETE,
              TestUtils.buildDeleteJob(sb.toString()),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      assertEquals("200", result.getBody().getRetCode());
    }
  }

  /**
   * step1:批量创建任务；step2:批量启动采集任务；step3:判断采集任务状态;(预期结果：success,success,success)
   *
   * @throws Exception
   */
  @Test(timeout = 5 * 60 * 1000)
  public void testbatchExecutorTest2() throws Exception {
    StringBuilder sb = new StringBuilder();
    String[] jobIds = new String[BATCH_SIZE];

    try {
      // step1:；批量创建任务
      for (int i = 0; i < BATCH_SIZE; i++) {
        long currTime = System.currentTimeMillis();
        String jobId = createJob("BatchExecutorTest_" + currTime + "_" + i);
        assertEquals(jobId != null, true);
        sb.append(jobId);
        if (i != BATCH_SIZE - 1) {
          sb.append(",");
        }

        dstTblNames[i] = "BatchExecutorTest_" + currTime + "_" + i;
      }
      System.out.println("批量创建任务ids=" + sb.toString());

      // step2:批量启动任务，预期success(多线程启动，判断任务执行状态)
      ResponseEntity<ResponseMsg> result =
          restTemplate.postForEntity(
              TestUtils.HOSTPORT + "/api/bdp/dcs" + "/job/JobRest/startJobByIds",
              TestUtils.buildStartJob(sb.toString()),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      assertEquals("200", result.getBody().getRetCode());

      // step3:查看任务执行状态
      Thread.sleep(60 * 1000);
      result =
          restTemplate.exchange(
              TestUtils.HOSTPORT
                  + "/api/bdp/dcs/job/JobRest/getJobList"
                  + "?jobStatus&sort&name="
                  + "批量测试门槛用例"
                  + "&jobType=1&currentPage=1&pageSize=10",
              HttpMethod.GET,
              TestUtils.buildGetHttpEntity(),
              ResponseMsg.class);
      ResponseMsg body = result.getBody();
      LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>) body.getResponseBody();
      List<Object> finalBody = (List<Object>) map.get("result");
      for (Object obj : finalBody) {
        LinkedHashMap<String, String> jobObj = (LinkedHashMap<String, String>) obj;
        JobDTO jobInfo = JSON.parseObject(JSON.toJSONString(jobObj), JobDTO.class);
        if (Arrays.asList(jobIds).contains(jobInfo.getId())) {
          System.out.println(
              String.format("任务id:%s,任务状态:%s", jobInfo.getId(), jobInfo.getJobStatus()));

          // 判断任务是否同步完成;
          assertEquals(7 == jobInfo.getJobStatus(), true);

          // 判断同步速度;（备注：源表中只有一行数据，大小固定）
          assertEquals(jobInfo.getReadSucceedBytes() == 18, true);

          break;
        }
      }
    } finally {
      // step3:批量删除任务
      ResponseEntity<ResponseMsg> result =
          restTemplate.exchange(
              TestUtils.HOSTPORT + "/api/bdp/dcs/job/JobRest" + "/deleteJobByIds",
              HttpMethod.DELETE,
              TestUtils.buildDeleteJob(sb.toString()),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      assertEquals("200", result.getBody().getRetCode());
    }
  }

  /**
   * step1:批量创建任务；step2:批量启动采集任务；step3:批量停止采集任务;(预期结果：success,success,success)
   *
   * @throws Exception
   */
  @Test(timeout = 5 * 60 * 1000)
  public void testbatchExecutorTest3() throws Exception {
    StringBuilder sb = new StringBuilder();
    String[] jobIds = new String[BATCH_SIZE];

    try {
      // step1:；批量创建任务
      for (int i = 0; i < BATCH_SIZE; i++) {
        long currTime = System.currentTimeMillis();
        String jobId = createJob("BatchExecutorTest_" + currTime + "_" + i);
        assertEquals(jobId != null, true);
        sb.append(jobId);
        if (i != BATCH_SIZE - 1) {
          sb.append(",");
        }

        dstTblNames[i] = "BatchExecutorTest_" + currTime + "_" + i;
      }
      System.out.println("批量创建任务ids=" + sb.toString());

      // step2:批量启动任务，预期success(多线程启动，判断任务执行状态)
      ResponseEntity<ResponseMsg> result =
          restTemplate.postForEntity(
              TestUtils.HOSTPORT + "/api/bdp/dcs" + "/job/JobRest/startJobByIds",
              TestUtils.buildStartJob(sb.toString()),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      assertEquals("200", result.getBody().getRetCode());

      // step3:；批量停止任务
      Thread.sleep(10 * 1000);
      result =
          restTemplate.postForEntity(
              TestUtils.HOSTPORT + "/api/bdp/dcs" + "/job/JobRest/finishJobByIds",
              TestUtils.buildStartJob(sb.toString()),
              ResponseMsg.class);
      //            assertEquals("200".equals(result.getBody().getRetCode()), true);
    } finally {
      // step3:批量删除任务，预期success
      ResponseEntity<ResponseMsg> result =
          restTemplate.exchange(
              TestUtils.HOSTPORT + "/api/bdp/dcs/job/JobRest" + "/deleteJobByIds",
              HttpMethod.DELETE,
              TestUtils.buildDeleteJob(sb.toString()),
              ResponseMsg.class);
      TestUtils.handleFailedRequest(result);
      assertEquals("200", result.getBody().getRetCode());
    }
  }
}
